#include <iostream>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/types.h>

#include "net/server.h"
#include "lua.hpp"
#include "tools/config.h"
#include "lua/mysql/connpool.hpp"

using namespace std;

//子进程数量
int g_child_process_num = 10;
//子进程列表
pid_t *g_pchild_pid_array = NULL;
//是否为子进程
bool g_is_child = false;

//app 名称
const char *g_app;

int lua_config()
{
    lua_State *L = luaL_newstate();
    luaL_openlibs(L);
    luaL_dofile(L, "../conf/weasel.lua");
    lua_close(L);
    return 1;
}

void pid_mark()
{
    pid_t pid = getpid();
    char path[PATH_MAX] = {0x0};
    sprintf(path, "../app/%s/%s.pid", g_app, g_app);
    FILE *pFile = fopen(path, "w");
    if (pFile == NULL)
    {
        perror("打开pid文件失败");
        return;
    }

    fprintf(pFile, "%d", pid);
    fclose(pFile);
}

bool read_pid(pid_t &pid)
{
    char path[PATH_MAX] = {0x0};
    sprintf(path, "../app/%s/%s.pid", g_app, g_app);
    FILE *pFile = fopen(path, "r");
    if (pFile == NULL)
    {
        perror("打开pid文件失败");
        return false;
    }

    fscanf(pFile, "%d", &pid);
    fclose(pFile);
    return true;
}

void create_app(const char *app)
{
    std::string cmd = "cp -r ../app/TemplateApp ../app/";
    cmd.append(app);
    system(cmd.c_str());
}

void run_app(const char *app)
{
    /*
    1.根据app名称 判断app是否存在
    2.并读取app下的settings.lua文件 读取配置
    */
    //初始化配置
    config::get()->init(app);
}

void stop_app(const char *app)
{
    pid_t pid;
    if (read_pid(pid))
    {
        if (-1 == kill(pid, SIGKILL))
        {
            perror("杀进程失败");
        }
    }
}

bool options(int argc, char **argv)
{
    if (argc == 2)
    {
    }
    else if (argc == 3)
    {
        if (0 == strcmp(argv[1], "createapp"))
        {
            create_app(argv[2]);
            //创建完成后结束程序
            exit(0);
        }
        else if (0 == strcmp(argv[1], "runapp"))
        {
            g_app = argv[2];
            run_app(argv[2]);
            //exit(0); //调试时临时添加
            return true;
        }
        else if (0 == strcmp(argv[1], "stopapp"))
        {
            g_app = argv[2];
            stop_app(argv[2]);
            //停止后结束程序
            exit(0);
        }
    }
    return true;
}

void handleterm(int sig)
{
    printf("主进程接受到停止信号，准备杀掉子进程\n");
    for (int i = 0; i < g_child_process_num; i++)
    {
        kill(g_pchild_pid_array[i], SIGTERM);
    }
    return;
}

bool create_child_process()
{
    for (int i = 0, j = 0; i < g_child_process_num; i++)
    {
        pid_t pid = fork();
        if (pid < 0)
        {
            perror("fork():");
            exit(1);
        }
        else if (pid == 0)
        {
            //子进程
            g_is_child = true;
            break;
        }
        else
        {
            //父进程空间，子进程id为pid
            g_is_child = false;
            g_pchild_pid_array[j] = pid;
            j++;
        }
    }
}

void init_mysql()
{
    //获取mysql配置
    st_mysql_config mysql_config = config::get()->get_mysql_config();
    //初始化mysql连接池
    mysql_conn_pool::get()->init(mysql_config.host,
                                 mysql_config.port,
                                 mysql_config.username,
                                 mysql_config.password,
                                 mysql_config.sourcename,
                                 mysql_config.max);
}

int main(int argc, char **argv)
{
    //处理命令行选项
    if (!options(argc, argv))
    {
        return 0;
    }

    //初始化mysql
    init_mysql();

    unsigned short port = 6518;
    g_pchild_pid_array = new pid_t[g_child_process_num];
    //实例化网络服务
    server *pServer = new server(port);
    //网络服务初始化
    if (!pServer->init())
    {
        return 0;
    }

    //创建子进程
    create_child_process();

    if (!g_is_child)
    {
        //记录主进程id
        pid_mark();

        //主进程业务处理
        while (true)
        {
            //注册Signal Terminate信号，并进行处理
            signal(SIGTERM, handleterm);
            pause();
        }
    }
    else
    {
        //子进程业务处理
        //处理epoll相关
        bool bret = pServer->init_epoll();
        if (!bret)
        {
            return 0;
        }

        while (true)
        {
            pServer->proc_epoll(50);
        }
    }

    delete[] g_pchild_pid_array;
    g_pchild_pid_array = NULL;

    //释放服务内存
    delete pServer;
    pServer = NULL;
    return 0;
}
